home *** CD-ROM | disk | FTP | other *** search
- ;**********************************************************
- ;
- ; Wide.a
- ;
- ; Author:
- ; Terry Teague
- ; based on work by Dale Semchishen, 1996
- ;
- ; Description:
- ; A 64 bit integer library for the 680x0 and PowerPC processors
- ;
- ; While this library is self-initializing you can choose
- ; to call WideInit() during application startup so that
- ; the first time you call a math routine it does not incur
- ; the extra time required for initialization.
- ;
- ; Most of the 64 bit routines in this library are available in
- ; QuickDraw GX or on the PowerPC. On the 680x0 if you include
- ; <GXTypes.h> or <GXMath.h> before "Wide.h" and compile this library,
- ; the QuickDraw GX traps will be used instead of the routines
- ; marked with "(gx)".
- ;
- ; This file implements the 68K assembly language routines for MPW
- ;
- ; Global functions:
- ; WideInit() - Initialize the Wide library (optional)
- ;
- ; WideAdd() - (gx) Add two 64 bit ints
- ; WideAdd32() - Add 32 bits to a 64 bit int
- ; WideAssign32() - Assign 32 bits to 64 bit int
- ; WideBitShift() - Shift a 64 bit number
- ; WideCompare() - (gx) Compare two 64 bits ints
- ; WideDivide() - (gx) Divide 32 bit int into 64 bit int with a 32 bit result
- ; WideMultiply() - (gx) Multiply two 32 bits ints for a 64 bit result
- ; WideNegate() - (gx) Negative value of a 64 bit int
- ; WideScale() - (gx) Highest order nonzero bit in a 64 bit number
- ; WideShift() - (gx) Shift a 64 bit number and round up
- ; WideSquareRoot() - (gx) return 32 bit square root of an unsigned 64 bit number
- ; WideSubtract32() - Subtract 32 bits from a 64 bit int
- ; WideSubtract() - (gx) Subtract a 64 bits int from a 64 bit int
- ; WideToDecStr() - Convert 64 bit int to a SANE 'decimal' string
- ; WideWideDivide() - (gx) Divide 32 bit int into 64 bit int with a 64 bit result
- ;
- ; Note:
- ; This library has been compiled under the following
- ; development systems:
- ; - Symantec C 68K 7.0.4
- ; - CodeWarrior 6 Lite (68K and PPC)
- ; - CodeWarrior 9 (68K and PPC) - Terry Teague
- ; - MPW 3.3.1 (MPWC 68K and PPCC PPC) - Terry Teague
- ; - MPW 3.4.1 (SC 68K and MrC PPC) - Terry Teague
- ;
- ;**********************************************************
-
- CASE OBJ
-
- include 'ToolUtils.a'
-
- IF ( &FINDSYM(&SYSGLOBAL,'MACSBUG') = 1 ) THEN
- ;◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊
- ; Macros for defining MacsBug procedure name / constants
- ;◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊
-
- MACRO
- M_ProcName &procedure_name
-
- STRING PASCAL
- dc.b $80, &procedure_name
- ALIGN 2
- dc.w $0000
- ENDM
-
- MACRO ; Forces a RTS for MacsBug to accept it as a proc name
- M_ProcNameRTS &procedure_name
-
- STRING PASCAL
- rts
- dc.b $80, &procedure_name
- ALIGN 2
- dc.w $0000
- ENDM
-
- ELSE
- MACRO
- M_ProcName &procedure_name
- ENDM
- MACRO
- M_ProcNameRTS &procedure_name
- ENDM
- ENDIF
-
- WIDE_HI EQU 0
- WIDE_LO EQU 4
-
- Wide_DivideU PROC EXPORT
- ;static void Wide_DivideU
- ;(
- ; wide *dividend_ptr, /* in/out: 64 bits to be divided */
- ; long divisor, /* in: value to divide by */
- ; long *remainder_ptr /* out: the remainder of the division */
- ;)
-
- DIVIDEND_PTR EQU 8
- DIVISOR EQU 12
- REMAINDER_PTR EQU 16
-
- LINK A6,#0
- MOVEM.L D2-D7,-(SP) ; save work registers
- CLR.L D0 ;
- CLR.L D1 ; D0-D1 is the quotient accumulator
- MOVE.L DIVIDEND_PTR(A6),A0 ;
- MOVE.L WIDE_HI(A0),D2 ;
- MOVE.L WIDE_LO(A0),D3 ; D2-D3 is the remainder accumulator
- CLR.L D4 ;
- MOVE.L D2,D5 ; D5 = copy of dividend.hi
- MOVE.L DIVISOR(A6),D6 ; D6 = copy of divisor
-
- MOVEQ.L #31,D7 ; FOR number of bits in divisor (see @div99:)
- @divloop:
- LSL.L #1,D0 ; shift quotient.hi accumulator left once
- LSL.L #1,D1 ; shift quotient.lo accumulator left once
- LSL.L #1,D4 ;
- LSL.L #1,D3 ; shift remainder accumulator left once
- BCC.S @div29 ; IF CC, a zero bit shifted out
- LSL.L #1,D2 ;
- BSET #0,D2 ;
- BRA.S @div30
- @div29:
- LSL.L #1,D2 ;
- @div30:
- SUB.L D6,D2 ; remainder -= divisor
- BCS.S @div50 ; IF CS, remainder is negative
- BSET #0,D1 ; quotient.lo |= 1
- BRA.S @div77 ;
- @div50:
- ADD.L D6,D2 ; remainder += divisor
- @div77:
- BTST D7,D5 ;
- BEQ.S @div90 ; IF EQ, bit not set in dividend.hi
- BSET #0,D4 ;
- @div90:
- CMP.L D6,D4 ;
- BCS.S @div99 ; IF CS, divisor < D4
- SUB.L D6,D4 ; D4 -= divisor
- BSET #0,D0 ; quotient.hi |= 1
- @div99:
- DBF D7,@divloop ; loop until D7 == -1
-
- MOVE.L DIVIDEND_PTR(A6),A0 ; output the remainder
- MOVE.L D0,WIDE_HI(A0) ;
- MOVE.L D1,WIDE_LO(A0) ;
- MOVE.L REMAINDER_PTR(A6),A0 ; output the remainder
- MOVE.L D2,(A0) ;
- MOVEM.L (SP)+,D2-D7 ; restore work registers
- UNLK A6
- RTS
-
- M_ProcName 'Wide_DivideU' ;debugger information
-
- ENDP
-
- Wide_DivS64 PROC EXPORT
- ;static long Wide_DivS64
- ;(
- ; const wide *dividend_ptr, /* in/out: 64 bits to be divided */
- ; long divisor, /* in: value to divide by */
- ; long *remainder_ptr, /* out: the remainder of the division */
- ; short *overflow_ptr /* out: flag indicating if overflow occured */
- ;)
- DIVIDEND_PTR EQU 8
- DIVISOR EQU 12
- REMAINDER_PTR EQU 16
- OVERFLOW_PTR EQU 20
-
- LINK A6,#0
- MOVE.L D2,-(SP)
- MOVEQ.L #1,D2 ; assume there is overflow
- MOVE.L DIVIDEND_PTR(A6),A0 ; A0 -> the dividend
- MOVE.L WIDE_LO(A0),D0 ;
- MOVE.L WIDE_HI(A0),D1 ; D1-D0 = 64 bit dividend
- DC.W $4C6E,$0C01,$000C ; DIVS.L DIVISOR(A6),D1-D0 - (64bit signed divide)
- BVS.S @divcont ; IF VS, we're overflowed
- CLR.W D2 ; ELSE, clear the overflow flag
- @divcont:
- MOVE.L REMAINDER_PTR(A6),A0 ; output remainder
- MOVE.L D1,(A0) ;
- MOVE.L OVERFLOW_PTR(A6),A0 ; output overflow flag
- MOVE.W D2,(A0) ;
- MOVE.L (SP)+,D2
- UNLK A6
- RTS
-
- M_ProcName 'Wide_DivS64' ;debugger information
-
- ENDP
-
- ;**********************************************************
-
- Wide_MulS64 PROC EXPORT
- ;static void Wide_MulS64
- ;(
- ; long multiplicand, /* in: first value to multiply */
- ; long multiplier, /* in: second value to multiply */
- ; wide *out_ptr /* out: 64 bits to be assigned */
- ;)
-
- MULTIPLICAND EQU 8
- MULTIPLIER EQU 12
- OUT_PTR EQU 16
-
- LINK A6,#0
- MOVE.L MULTIPLICAND(A6),D0 ;
- DC.W $4C2E,$0C01,$000C ; MULS.L MULTIPLIER(A6),D1-D0 - 64bit signed multiply
- MOVE.L OUT_PTR(A6),A0 ;
- MOVE.L D0,WIDE_LO(A0) ; WIDE_LO defined earlier
- MOVE.L D1,WIDE_HI(A0) ; WIDE_HI defined earlier
- UNLK A6
- RTS
-
- M_ProcName 'Wide_MulS64' ;debugger information
-
- ENDP
-
- END